package com.ruoyi.aitcommon.utils;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.software.os.OperatingSystem;

import javax.annotation.PostConstruct;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

@Component
public class HardwareInfoManager {
    private static JSONObject allInfo=null;

    @PostConstruct
    public void init() throws Exception{
        getAllInfo();
    }

    public static String getCPUID() throws Exception {
        return getAllInfo().getJSONObject("CPU Info").getString("Processor ID");
    }

    public static JSONObject getAllInfo() throws Exception {
        if(allInfo==null){
            allInfo = new JSONObject();
            allInfo.put("date", DateUtil.date().toString());
            SystemInfo systemInfo = new SystemInfo();
            // --- CPU Info ---
            com.alibaba.fastjson.JSONObject cpuInfo = new com.alibaba.fastjson.JSONObject();
            CentralProcessor processor = systemInfo.getHardware().getProcessor();
            cpuInfo.put("Processor ID", processor.getProcessorIdentifier().getProcessorID());
            cpuInfo.put("Physical Package Count", processor.getPhysicalPackageCount());
            cpuInfo.put("Physical Core Count", processor.getPhysicalProcessorCount());
            cpuInfo.put("Logical Processor Count", processor.getLogicalProcessorCount());
            allInfo.put("CPU Info", cpuInfo);

            // --- Memory Info ---
            com.alibaba.fastjson.JSONObject memoryInfo = new com.alibaba.fastjson.JSONObject();
            GlobalMemory memory = systemInfo.getHardware().getMemory();
            long totalMemory = memory.getTotal();
            long availableMemory = memory.getAvailable();
            long usedMemory = totalMemory - availableMemory;
            double memoryUsageRate = (double) usedMemory / totalMemory;
            memoryInfo.put("Total Memory (Bytes)", totalMemory);
            memoryInfo.put("Available Memory (Bytes)", availableMemory);
            memoryInfo.put("Used Memory (Bytes)", usedMemory);
            memoryInfo.put("Memory Usage Rate (%)", String.format("%.2f", memoryUsageRate * 100));
            allInfo.put("Memory Info", memoryInfo);

            // --- Operating System Info ---
            com.alibaba.fastjson.JSONObject osInfo = new com.alibaba.fastjson.JSONObject();
            OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
            osInfo.put("OS Family", operatingSystem.getFamily());
            osInfo.put("OS Version", operatingSystem.getVersionInfo().getVersion());
            osInfo.put("OS Manufacturer", operatingSystem.getManufacturer());
            osInfo.put("Bitness", operatingSystem.getBitness());
            allInfo.put("Operating System Info", osInfo);

            // --- BIOS Info ---
            com.alibaba.fastjson.JSONObject biosInfo = new com.alibaba.fastjson.JSONObject();
            Firmware bios = systemInfo.getHardware().getComputerSystem().getFirmware();
            biosInfo.put("BIOS Manufacturer", bios.getManufacturer());
            biosInfo.put("BIOS Version", bios.getVersion());
            biosInfo.put("BIOS Release Date", bios.getReleaseDate());
            allInfo.put("BIOS Info", biosInfo);

            // --- Baseboard (Motherboard) Info ---
            com.alibaba.fastjson.JSONObject baseboardInfo = new com.alibaba.fastjson.JSONObject();
            Baseboard baseboard = systemInfo.getHardware().getComputerSystem().getBaseboard(); // 主板信息
            baseboardInfo.put("Manufacturer", baseboard.getManufacturer());
            baseboardInfo.put("Model", baseboard.getModel());
            baseboardInfo.put("Serial Number", baseboard.getSerialNumber());
            baseboardInfo.put("Version", baseboard.getVersion());
            allInfo.put("Baseboard Info", baseboardInfo);

            // --- Graphics Cards Info ---
            JSONArray graphicsCardsInfo = new JSONArray();
            List<GraphicsCard> graphicsCards = systemInfo.getHardware().getGraphicsCards(); // GPU 信息
            for (GraphicsCard gpu : graphicsCards) {
                com.alibaba.fastjson.JSONObject gpuInfo = new com.alibaba.fastjson.JSONObject();
                gpuInfo.put("Name", gpu.getName());
                gpuInfo.put("Vendor", gpu.getVendor());
                gpuInfo.put("Version", gpu.getVersionInfo());
                gpuInfo.put("VRAM", gpu.getVRam() + " MB"); // VRAM in MB
                graphicsCardsInfo.add(gpuInfo);
            }
            allInfo.put("Graphics Cards", graphicsCardsInfo);

            // --- Network Interfaces Info ---
            JSONArray networkInterfacesInfo = new JSONArray();
            List<NetworkIF> networkIFs = systemInfo.getHardware().getNetworkIFs();
            for (NetworkIF net : networkIFs) {
                com.alibaba.fastjson.JSONObject networkInterfaceInfo = new com.alibaba.fastjson.JSONObject();
                networkInterfaceInfo.put("Name", net.getName());
                networkInterfaceInfo.put("MAC Address", net.getMacaddr());
                networkInterfaceInfo.put("IP Addresses", getIpAddresses(net));
                networkInterfacesInfo.add(networkInterfaceInfo);
            }
            allInfo.put("Network Interfaces", networkInterfacesInfo);
        }
        return allInfo;
    }

    private static List<String> getIpAddresses(NetworkIF netIf) throws SocketException {
        List<String> ipAddresses = new ArrayList<>();
        try {
            Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
            while (interfaces.hasMoreElements()) {
                NetworkInterface networkInterface = interfaces.nextElement();
                if (networkInterface.getName().equals(netIf.getName())) {
                    Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
                    while (inetAddresses.hasMoreElements()) {
                        InetAddress inetAddress = inetAddresses.nextElement();
                        if (!inetAddress.isLoopbackAddress() && inetAddress.isSiteLocalAddress()) {
                            ipAddresses.add(inetAddress.getHostAddress());
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return ipAddresses;
    }
}
